﻿using System;
using System.Globalization;
using QAToolsAddin.Components;
using QAToolsAddin.GenericDialogs;
using QAToolsAddin.GenericDialogs.Fields;
using Excel = Microsoft.Office.Interop.Excel;

namespace QAToolsAddin.UI {
    class Distrib {
        private readonly Excel.Application _excelapp;
        private readonly Excel.Range _range;
        private CultureInfo _culture;
        private FieldNumber _fnb;

        public Distrib(Excel.Application application, CultureInfo culture) {
            try {
                _excelapp = application;
                _culture = culture;
                _range = application.ActiveWindow.RangeSelection;
                _fnb = new FieldNumber("Number of rows", "", 10000, 1);
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void Beta() {
            var f1 = new FieldNumber("Alpha", "", 1, 0);
            var f2 = new FieldNumber("Beta", "", 1, 0);
            new InputBox(_excelapp, "Generate Beta distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Beta(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Bernoulli() {
            var f1 = new FieldNumber("Alpha", "", 0.5, 0, 1);
            new InputBox(_excelapp, "Generate Bernoulli distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Bernoulli(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void BetaPrime() {
            var f1 = new FieldNumber("Alpha", "", 2, 1);
            var f2 = new FieldNumber("Beta", "", 2, 1);
            new InputBox(_excelapp, "Generate BetaPrime distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new BetaPrime(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Binomial() {
            var f1 = new FieldNumber("Alpha", "", 0.5d, 0, 1);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Binomial distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Binomial(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Cauchy() {
            var f1 = new FieldNumber("Alpha", "", 1d);
            var f2 = new FieldNumber("Gamma", "", 1d, 0);
            new InputBox(_excelapp, "Generate Cauchy distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Cauchy(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Chi() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            new InputBox(_excelapp, "Generate Cauchy distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Chi(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void ChiSquare() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            new InputBox(_excelapp, "Generate ChiSquare distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new ChiSquare(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void ContinuousUniform() {
            var f1 = new FieldNumber("Alpha", "", 0d, 0, 1);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate ContinuousUniform distribution", _fnb, f1, f2).Show(delegate {
                if (f1.Value > f2.Value)
                    throw new InputError("Alpha has to be inferior to Beta");
                CellsOperator.AddDataToRange(_range, new ContinuousUniform(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void DiscreteUniform() {
            var f1 = new FieldNumber("Alpha", "", 0d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate DiscreteUniform distribution", _fnb, f1, f2).Show(delegate {
                if (f1.Value > f2.Value)
                    throw new InputError("Alpha has to be inferior to Beta");
                CellsOperator.AddDataToRange(_range, new DiscreteUniform(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Erlang() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Erlang distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Erlang(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Exponential() {
            var f1 = new FieldNumber("Mean", "", 1d, 0);
            new InputBox(_excelapp, "Generate Exponential distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Exponential(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Fisher() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Fisher distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Fisher(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Gamma() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Theta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Gamma distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Gamma(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Geometric() {
            var f1 = new FieldNumber("Probability", "", 0.5d, 0, 1);
            new InputBox(_excelapp, "Generate Geometric distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Geometric(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Laplace() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Mu", "", 0d);
            new InputBox(_excelapp, "Generate Laplace distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Laplace(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Lognormal() {
            var f1 = new FieldNumber("Mu", "", 0d);
            var f2 = new FieldNumber("Sigma", "", 1d, 0);
            new InputBox(_excelapp, "Generate Lognormal distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Lognormal(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Normal() {
            var f1 = new FieldNumber("Mean", "", 1d);
            var f2 = new FieldNumber("Sigma", "", 1d, 0);
            new InputBox(_excelapp, "Generate Normal distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Normal(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Pareto() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Pareto distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Pareto(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Poisson() {
            var f1 = new FieldNumber("Lambda", "", 1d, 0);
            new InputBox(_excelapp, "Generate Poisson distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Poisson(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Power() {
            var f1 = new FieldNumber("Alpha", "", 1d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            new InputBox(_excelapp, "Generate Power distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Power(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Rayleigh() {
            var f1 = new FieldNumber("Sigma", "", 1d, 0);
            new InputBox(_excelapp, "Generate Rayleigh distribution", _fnb, f1).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Rayleigh(f1.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Triangular() {
            var f1 = new FieldNumber("Alpha", "", 0d, 0);
            var f2 = new FieldNumber("Beta", "", 1d, 0);
            var f3 = new FieldNumber("Gamma", "", 0.5d, 0);
            new InputBox(_excelapp, "Generate Triangular distribution", _fnb, f1, f2, f3).Show(delegate {
                if (f1.Value < f2.Value && f1.Value <= f3.Value)
                    throw new InputError("Alpha is not valid");
                if (f2.Value > f1.Value && f2.Value >= f3.Value)
                    throw new InputError("Beta is not valid");
                if (f3.Value >= f1.Value && f3.Value <= f2.Value)
                    throw new InputError("Beta is not valid");
                CellsOperator.AddDataToRange(_range, new Triangular(f1.Value ?? 0, f2.Value ?? 0, f3.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

        public void Weibull() {
            var f1 = new FieldNumber("Shape k", "", 1d, 0, true);
            var f2 = new FieldNumber("Scale λ", "", 1d, 0, true);
            new InputBox(_excelapp, "Generate Weibull distribution", _fnb, f1, f2).Show(delegate {
                CellsOperator.AddDataToRange(_range, new Weibull(f1.Value ?? 0, f2.Value ?? 0).GetDoubles((int)_fnb.Value));
            });
        }

    }
}
